package com.wsk.realm;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;

/**
 * Created by wsk1103 on 2017/9/15.
 * 自定义的指定shiro验证用户登录的类
 * 定义2个用户，wsk和xc，wsk不具备任何的角色和权限，xc具有admin角色和admin:manage权限
 */
public class MyRealm extends AuthorizingRealm {
    /*
    为当前登录的Subject授予角色和权限
    本例中该方法的调用时机为需要授权资源被访问时
    并且每次访问需要授权的资源都会执行该方法中的逻辑，表明本例中默认并为启用AuthorizationCache(缓存)
    若使用了Spring3.1开始提供的ConcurrenMapCache支持，则可以灵活决定使用启用AuthorizationCache
    比如从数据库获取权限信息时，先访问Spring3.1提供的缓存，而不是使用shiro提供的AuthorizationCache
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
//        获得当前登录的用户名，等价与
        //(String)principalCollection.fromRealm(this.getName()).iterator.next();
        String currentUsername = (String) super.getAvailablePrincipal(principalCollection);
//        List<String> roleList = new ArrayList<>();
//        List<String> permissionList = new ArrayList<>();
        //从数据库获取当前登录用户的详细信息
//        User user = userService.getByUsername(currentUsername);
//        if (user != null) {
//            //实体类user包含用户角色的实体类信息
//            if (null != user.getRoles() ){
//                for (Role role :user.getRoles()){
//                    roleList.add(role.getName());
//                    if (null != role.getPermission() && role.getPermission.size()>0){
//                        //获得权限
//                        for (Permission pmss : role.getPermission()){
//                            if (!StringUtils.isEmpty(pmss.getPermission())) {
//                                permissionList.add(pmss.getPermission);
//                            }
//                        }
//                    }
//                }
//            }
//        } else {
//            throw new AuthorizationException();
//        }
        //为当前用户设置角色和权限
//        SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo();
//        simpleAuthenticationInfo.addRoles(roleList);
//        simpleAuthenticationInfo.addStringPermissions(permissionList);
        //硬编码
        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
        if (null != currentUsername && "xc".equals(currentUsername)) {
            //添加一个角色，不是配置意义上的添加，二手证明该用户拥有admin角色
            simpleAuthorizationInfo.addRole("admin");
            //添加权限
            simpleAuthorizationInfo.addStringPermission("admin:manage");
            System.out.println("已为用户【xc】授予[admin]角色和[admin:manage]权限");
            return simpleAuthorizationInfo;
        }
        //如果该方法什么都不做直接返回null，会导致任何用户访问/admin/listUser.jsp时都会自动跳转到unauthorizedUrl指定的地址
        //详见applicationContext.xml中的<bean id = "shiroFilter">的配置
        return null;
    }

    //验证当前登录的Subject
    //本例中该方法掉头时机为LoginController.login()方法中执行的Subject.login()
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        //获取基于用户名和密码的令牌
        //实际上这个authcToken是从LoginController里面currentUser.login(token)传过来的
        //两个token的引用都是一样的，本例中是org.apache.shiro.authc.UsernamePasswordToken
        UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
        System.out.println("验证当前的Subject获取到的token为" + token);
//        User user = userService.getByUsername(token.getUsername());
//        if (null != user) {
//            AuthenticationInfo info = new SimpleAuthenticationInfo(user.getUsername(),user.getPassword());
//            this.setSession("currentUser", user);
//            return info;
//        } else {
//            return null;
//        }
        //此处不需要比对，比对的逻辑shiro会做，我们只需要返回一个和令牌相关的正确的验证信息
        //第一个参数天登录用户名，第二个参数填合法的登录密码（可以从数据库中获取）
        //在虽有的登录页面上就只有这里指定的用户和密码才能通过验证
        if ("xc".equals(token.getUsername())) {
            AuthenticationInfo info = new SimpleAuthenticationInfo("xc", "xc1225", this.getName());
            this.setSession("currentUser", "xc");
            return info;
        } else if ("wsk".equals(token.getUsername())) {
            AuthenticationInfo info = new SimpleAuthenticationInfo("wsk", "wsk1103", this.getName());
            this.setSession("currentUser", "wsk");
            return info;
        }
        return null;
    }

    private void setSession(Object key, Object value) {
        Subject currentUser = SecurityUtils.getSubject();
        if (null != currentUser) {
            Session session = currentUser.getSession();
            System.out.println("session默认超时时间为[" + session.getTimeout() + "]毫秒");
            if (null != session) {
                session.setAttribute(key,value);
            }
        }
    }
}
